#region License
// Copyright 2007-2008 Rory Plaire (codekaizen@gmail.com)
/*
 * This license governs use of the accompanying software. If you use the software, you
 * accept this license. If you do not accept the license, do not use the software.
 * 
 * 1. Definitions
 * The terms "reproduce," "reproduction," "derivative works," and "distribution" have the
 * same meaning here as under U.S. copyright law.
 * A "contribution" is the original software, or any additions or changes to the software.
 * A "contributor" is any person that distributes its contribution under this license.
 * "Licensed patents" are a contributor's patent claims that read directly on its contribution.
 * 
 * 2. Grant of Rights
 * (A) Copyright Grant- Subject to the terms of this license, including the license conditions 
 *     and limitations in section 3, each contributor grants you a non-exclusive, worldwide, 
 *     royalty-free copyright license to reproduce its contribution, prepare derivative works 
 *     of its contribution, and distribute its contribution or any derivative works that you create.
 * (B) Patent Grant- Subject to the terms of this license, including the license conditions and 
 *     limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free 
 *     license under its licensed patents to make, have made, use, sell, offer for sale, import, 
 *     and/or otherwise dispose of its contribution in the software or derivative works of the 
 *     contribution in the software.
 * 
 * 3. Conditions and Limitations
 * (A) No Trademark License- This license does not grant you rights to use any contributors' 
 *     name, logo, or trademarks.
 * (B) If you bring a patent claim against any contributor over patents that you claim are 
 *     infringed by the software, your patent license from such contributor to the software 
 *     ends automatically.
 * (C) If you distribute any portion of the software, you must retain all copyright, patent, 
 *     trademark, and attribution notices that are present in the software.
 * (D) If you distribute any portion of the software in source code form, you may do so only under 
 *     this license by including a complete copy of this license with your distribution. If you 
 *     distribute any portion of the software in compiled or object code form, you may only do so 
 *     under a license that complies with this license.
 * (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no 
 *     express warranties, guarantees or conditions. You may have additional consumer rights under 
 *     your local laws which this license cannot change. To the extent permitted under your local laws, 
 *     the contributors exclude the implied warranties of merchantability, fitness for a particular 
 *     purpose and non-infringement.
 * 
 */
#endregion

using System;

namespace NPack.Numeric.Interfaces
{
    /// <summary>
    /// An interface to a generic matrix.
    /// </summary>
    /// <typeparam name="T">Type of element in the matrix.</typeparam>
    public interface IMatrix<T> : IEquatable<IMatrix<T>>, IComparable<IMatrix<T>>, 
                                  IComputable<IMatrix<T>>
        //where T : IEquatable<T>, IComparable<T>, IComputable<T>, IConvertible
    {
        /// <summary>
        /// Gets the determinant for the matrix, if it exists.
        /// </summary>
        Double Determinant { get; }

        /// <summary>
        /// Gets the number of columns in the matrix.
        /// </summary>
        Int32 ColumnCount { get; }

        /// <summary>
        /// Gets the format of the matrix, either row-major or column-major.
        /// </summary>
        MatrixFormat Format { get; }

        /// <summary>
        /// Gets true if the matrix is singular (non-invertible).
        /// </summary>
        Boolean IsSingular { get; }

        /// <summary>
        /// Gets true if the matrix is invertible (non-singular).
        /// </summary>
        Boolean IsInvertible { get; }

        /// <summary>
        /// Gets the inverse of the matrix, if one exists.
        /// </summary>
        IMatrix<T> Inverse { get; }

        /// <summary>
        /// Gets true if the matrix is square (<c>RowCount == ColumnCount != 0</c>).
        /// </summary>
        Boolean IsSquare { get; }

        /// <summary>
        /// Gets true if the matrix is symmetrical.
        /// </summary>
        Boolean IsSymmetrical { get; }

        /// <summary>
        /// Gets the number of rows in the matrix.
        /// </summary>
        Int32 RowCount { get; }

        /// <summary>
        /// Gets or sets an element in the matrix.
        /// </summary>
        /// <param name="row">The index of the row of the element.</param>
        /// <param name="column">The index of the column of the element.</param>
        /// <returns>The value of the element at the specified row and column.</returns>
        T this[Int32 row, Int32 column] { get; set; }

        /// <summary>
        /// Makes an element-by-element copy of the matrix.
        /// </summary>
        /// <returns>An exact copy of the matrix.</returns>
        IMatrix<T> Clone();

        /// <summary>
        /// Gets a submatrix.
        /// </summary>
        /// <param name="rowIndexes">The indexes of the rows to include.</param>
        /// <param name="startColumn">The starting column to include.</param>
        /// <param name="endColumn">The ending column to include.</param>
        /// <returns>
        /// A submatrix with rows given by <paramref name="rowIndexes"/> and columns 
        /// <paramref name="startColumn"/> through <paramref name="endColumn"/>.
        /// </returns>
        IMatrix<T> GetMatrix(Int32[] rowIndexes, Int32 startColumn, Int32 endColumn);

        /// <summary>
        /// Returns the transpose of the matrix.
        /// </summary>
        /// <returns>The matrix with the rows as columns and columns as rows.</returns>
        IMatrix<T> Transpose();
    }
}